import { EntityBase } from '@/core';
import { switchMap } from 'rxjs/internal/operators';
import { Observable, of } from 'rxjs';

export class WXLocationEntity extends EntityBase {
  public latitude = 41.79; // 纬度，浮点数，范围为90 ~ -90
  public longitude = 123.39; // 经度，浮点数，范围为180 ~ -180。
  public speed: number = undefined; // 速度，以米/每秒计
  public accuracy: number = undefined; // 位置精度
  public name: string = undefined;
  public address: string = undefined;
}

class LocationRouteEntity {
  public latitude = 0;
  public longitude = 0;
  public name = '';
  public address = '';
  public scale = 28;
  constructor(source: LocationRoute) {
    this.latitude = Number(source.latitude);
    this.longitude = Number(source.longitude);
    this.name = source.address_name;
    this.address = source.address;
  }
}

export interface LocationRoute {
  latitude: number;
  longitude: number;
  address: string;
  address_name: string;
}

enum AuthorizationState {
  unauthorized,
  authorized,
  refused,
} // 拒绝只可以出现一次

class LocationHelper {
  private preventDebounce = false; // 阻止重复点击

  /**
   * 打开地图
   *
   * @param {LocationRoute} source
   * @param {(state: boolean) => {}} [callback] 完成后的回调
   * @memberof LocationHelper
   */
  public openLocation(source: LocationRoute, callback?: (state: boolean) => {}) {
    if (!this.preventDebounce) {
      this.preventDebounce = true;
      const parking = new LocationRouteEntity(source);
      this.locationAuthorize().pipe(switchMap((authState: AuthorizationState) => {
        switch (authState) {
          case AuthorizationState.authorized:
            return of(true);
          case AuthorizationState.unauthorized:
            return this.againLocationAuthorize();
          case AuthorizationState.refused:
          default:
            return of(false);
        }
      }), switchMap((againAuth: boolean) => {
        if (againAuth) {
          return Observable.create((observe: any) => {
            Taro.getLocation({
              type: 'gcj02',
              // 返回可以用于wx.openLocation的经纬度
              success: () => {
                Taro.openLocation(parking);
                observe.next(true);
                observe.complete();
              },
              fail: () => {
                Taro.showToast({
                  title: '调用地图失败',
                  icon: 'none',
                });
                observe.next(false);
                observe.complete();
              },
            });
          });
        } else {
          return of(false);
        }
      })).subscribe((state: any) => {
        this.preventDebounce = false;
        callback && callback(state);
      });
    }
  }

  /**
   * 获取地理位置授权
   * @private
   * @returns {rxjs.Observable<AuthorizationState>} 返回授权状态
   * @memberof LocationHelper
   */
  private locationAuthorize(): Observable<AuthorizationState> {
    return Observable.create((observe: any) => {
      Taro.getSetting({
        success: (settingRes: any) => {
          if (settingRes.authSetting['scope.userLocation']) {
            observe.next(AuthorizationState.authorized);
            observe.complete();
          } else {
            Taro.authorize({
              scope: 'scope.userLocation',
              success: () => {
                observe.next(AuthorizationState.authorized);
                observe.complete();
              }, fail: () => {
                observe.next(AuthorizationState.unauthorized);
                observe.complete();
              },
            });
          }
        }, fail: () => {
          // 获取配置信息错误认为是没有授权
          observe.next(AuthorizationState.unauthorized);
          observe.complete();
        },
      });
    });
  }

  /**
   * 重新获取地理位置授权
   * @private
   * @returns
   * @memberof LocationHelper
   */
  private againLocationAuthorize(): Observable<boolean> {
    return Observable.create((observe: any) => {
      const failProcess = (failObserve: any) => {
        Taro.showToast({
          title: '调用授权窗口失败',
          icon: 'none',
          success: () => {
            failObserve.next(false);
            failObserve.complete();
          },
        });
      };
      Taro.zmyShowConfirm('找不到您的位置，请开启定位', () => {
        Taro.openSetting({
          success: (dataAuth: any) => {
            if (dataAuth.authSetting['scope.userLocation'] === true) {
              // 再次授权成功，调用wx.getLocation的API
              observe.next(true);
              observe.complete();
            } else {
              failProcess(observe);
            }
          }, fail: () => {
            failProcess(observe);
          },
        });
      }, () => {
        failProcess(observe);
      }, '', '取消', '去开启');
    });
  }
}
const locationHelper = new LocationHelper();
export default locationHelper;
